#include "SpaceInvadersPCH.h"
#include "Material.h"

void RenderMethod::Initialise(gk::GpuProgramHandle hGpuProgram)
{
	m_constantBufferSet.Create(hGpuProgram);
	m_hGpuProgram = hGpuProgram;
}

void RenderMethod::Release()
{
	m_constantBufferSet.Release();
}

void RenderMethod::SetParam(Data_RenderData::RenderData* pRenderData, cr::uint32_t idxParam)
{
	const Data_RenderData::Parameter& srcParam = pRenderData->m_pParameters[idxParam];
	cr::uint8_t* pInitData = pRenderData->m_pRawBytes + srcParam.m_idxInitData;
	gk::GpuProgramConstantHandle hConstant = m_hGpuProgram->GetConstantByName(srcParam.m_name);
	if (hConstant.IsValid())
	{
		switch (srcParam.m_type)
		{
		case shared::prehash::hs_Float1:
			{
				float* pInitFloats = (float*)pInitData;
				GetConstantBufferSet()->SetConstant(hConstant, pInitFloats[0]);
				break;
			}

		case shared::prehash::hs_Float2:
			{
				float* pInitFloats = (float*)pInitData;
				cr::Vec4f vec(pInitFloats[0],pInitFloats[1],0,0);
				GetConstantBufferSet()->SetConstant(hConstant, vec);
				break;
			}

		case shared::prehash::hs_Float3:
			{
				float* pInitFloats = (float*)pInitData;
				cr::Vec4f vec(pInitFloats[0],pInitFloats[1],pInitFloats[2],0);
				GetConstantBufferSet()->SetConstant(hConstant, vec);
				break;
			}
		case shared::prehash::hs_Float4:
			{
				float* pInitFloats = (float*)pInitData;
				cr::Vec4f vec(pInitFloats[0],pInitFloats[1],pInitFloats[2],pInitFloats[3]);
				GetConstantBufferSet()->SetConstant(hConstant, vec);
				break;
			}
		case shared::prehash::hs_Texture:
			{
				Data_RenderData::Texture& srcTexture = pRenderData->m_pTextures[srcParam.m_idxInitData];
				GetConstantBufferSet()->SetConstant(hConstant, (gk::Texture*)srcTexture.m_runtimeData);
				break;
			}
		}
	}
}

RenderMethod& Material::CreateRenderMethod(cr::HashedString hsName, gk::GpuProgramHandle hGpuProgram)
{
	CR_ASSERT(m_renderMethods.find(hsName) == m_renderMethods.end());
	RenderMethod& rm = m_renderMethods[hsName];
	rm.Initialise(hGpuProgram);
	return rm;
}

RenderMethod& Material::GetRenderMethod(cr::HashedString hsName)
{
	CR_ASSERT(m_renderMethods.find(hsName) != m_renderMethods.end());
	return m_renderMethods[hsName];
}

void Material::ReleaseRenderMethods()
{
	for (TRenderMethodMap::iterator it = m_renderMethods.begin(), end = m_renderMethods.end(); it != end; ++it)
	{
		RenderMethod& rm = it->second;
		rm.Release();
	}
}